package com.shiguiwu.springmybatis.spring.componentscan;

import com.shiguiwu.springmybatis.spring.componentscan.filter.MyFilter;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;

/**
 * @description: spring批量注册组件
 * @author: stone
 * @date: Created by 2021/9/28 17:01
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.spring.componentscan
 *
 *
 * todo excludeFilters
 * 配置排除的过滤器，满足这些过滤器的类不会被注册到容器中，用法上面和includeFilters用一样，这
 * 个我就不演示了，可以自己玩玩
 */
//默认情况下
//@ComponentScan
//
//======================================================================
//指定包名,若包被重名了，会导致扫描会失效
//@ComponentScan({
//        "com.shiguiwu.springmybatis.spring.componentscan.controller",
//        "com.shiguiwu.springmybatis.spring.componentscan.dao"
//})


//======================================================================
//指定类，也可以是接口 原理是会扫描这个类下所有类和子包
//@ComponentScan(basePackageClasses = IScan.class)


//======================================================================
//自定义注解，不用spring默认的注解也可以注册容器 useDefaultFilters=true的时候，spring的注解也会生效,ffalse不会，只会用我们的
//@ComponentScan(
//     useDefaultFilters = false,
//     includeFilters = {
//             @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = MyBean.class)
//     }
//)
//======================================================================


//通过扫描给定接口的子类
//@ComponentScan(
//        useDefaultFilters = false,
//        includeFilters = {
//                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = IScan.class)
//        }
//)

//============================================================================
//通过自定义子接口方式,需要实现一个接口

@ComponentScan(
        useDefaultFilters = false,
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.CUSTOM, classes = MyFilter.class)
        }
)

//ComponentScan 注解被org.springframework.context.annotation.ConfigurationClassPostProcessor
//以下注解也是他处理的
/**
 * @PropertySource
 * @Import
 * @ImportResource
 * @Compontent
 */
public class ComponentScanTests {


    /**
     * 1. @ComponentScan用于批量注册bean，spring会按照这个注解的配置，递归扫描指定包中的所
     * 有类，将满足条件的类批量注册到spring容器中
     * 2. 可以通过value、basePackages、basePackageClasses 这几个参数来配置包的扫描范围
     * 3. 可以通过useDefaultFilters、includeFilters、excludeFilters这几个参数来配置类的过滤器，
     * 被过滤器处理之后剩下的类会被注册到容器中
     * 4. 指定包名的方式配置扫描范围存在隐患，包名被重命名之后，会导致扫描实现，所以一般我们在需
     * 要扫描的包中可以创建一个标记的接口或者类，作为basePackageClasses的值，通过这个来控制
     * 包的扫描范围
     * 5. @CompontScan注解会被ConfigurationClassPostProcessor类递归处理，最终得到所有需要注
     * 册的类。
     * @param args
     */
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ComponentScanTests.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName + "----------->" + context.getBean(beanDefinitionName));
        }
    }


}
